package AM;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Main_Frame extends JFrame implements Runnable {

	// 화면 구성에 필요한 객체들..

	CardLayout card;
	JPanel card1, card2, card3;

	// 로그인 화면에 필요한 객체들
	JPanel lCenter_p;
	JTextField name_tf;
	JButton login_bt;
	JLabel image;
	String name;

	// 자원을 주고 받기 위한 객체들
	Socket s;
	ObjectInputStream in;
	ObjectOutputStream out;

	Thread thread;

	CatchHeroin_Client pClient; // CatchHeroin_Client 객체를 멤버로 받아놓는다. -->socket ,
								// stream 멤버 사용 원활히 하기 위해..

	public Main_Frame() {
		
		setLayout(card = new CardLayout());

		image = new JLabel(new ImageIcon("src/img/hero.jpg"));
		card1 = new JPanel();
		lCenter_p = new JPanel();
		name_tf = new JTextField(12);
		login_bt = new JButton(" 들어가기 ");

		lCenter_p.add(name_tf, new FlowLayout(FlowLayout.CENTER));
		lCenter_p.add(login_bt, new FlowLayout(FlowLayout.RIGHT));

		card1.setLayout(new FlowLayout(FlowLayout.CENTER));
		card1.add(image);
		card1.add(lCenter_p);

		// 화면 구성을 모두 마친 카드를 현재 Frame이 가지는
		// Container에 추가해야 한다.
		this.getContentPane().add(card1, "card1");

		// 게임화면구성
		card2 = new JPanel(new BorderLayout());

		// 이벤트등록
		login_bt.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 로그인 버튼을 선택했을 때만 수행하는 곳이다.
				// 이때!
				// 사용자가 입력한 대화명을 가져온다.
				name = name_tf.getText().trim();

				if (name.length() > 0) {
					
					serverConneted(name);

				} else {
					JOptionPane.showMessageDialog(Main_Frame.this,
							"대화명을 입력하세요!");
					name_tf.setText("");// 청소
					name_tf.requestFocus();// 커서 놓기
					return;// 제어권 반환!
				}
			}
		});

		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				
				
				try {
					Protocol p = new Protocol();
					p.setCmd(Protocol.EXIT_CLIENT);
					out.writeObject(p);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}

		});

		setBounds(200, 200, 400, 300);
		setVisible(true);
		setResizable(false);

	}

	/**
	 * 서버 연결시 nickName을 전달한다. (기존 nickName과 중복 되지 않도록 비교하여 true/false 값을 반환
	 * 받는다.) cmd = 0 으로 전달
	 */
	private void serverConneted(String nick_name) {

		try {
			s = new Socket("localhost", 3333);
			System.out.println("serverConneted :: s socket send to server");
			out = new ObjectOutputStream(s.getOutputStream());
			in = new ObjectInputStream(s.getInputStream());

			thread = new Thread(this);
			thread.start();

			// 로그인을 했으므로 대화명을 서버쪽으로
			// 보내준다.

			System.out.println("serverConneted :: s socket protocol creates.");
			Protocol p = new Protocol();
			p.setCmd(Protocol.LOG_IN);
			p.setMsg(nick_name);

			out.writeObject(p);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	@Override
	public void run() {
		String nickName = "";
		main_thread: while (true) {
			try {

				Object obj = in.readObject();
				Protocol p = (Protocol) obj;
				
				
				
				switch (p.getCmd()) {
				case Protocol.LOG_IN:
					
					if (p.getMsg().equals("duplicated_nickname")) {
						JOptionPane.showMessageDialog(Main_Frame.this,
								"중복된 닉네임입니다!");
						name_tf.setText("");// 청소
						name_tf.requestFocus();// 커서 놓기

						// p.setCmd(Protocol.EXIT_CLIENT);
						// out.writeObject(p);

					} else {
						
						
						
						if (p.getClientLength() < Protocol.CLIENT_MAX_SIZE) {
							p = new Protocol();
							p.setCmd(Protocol.CLIENT_LOG_IN);
							p.setMsg(name);
							nickName = name;
							
							// 게임 화면을 생성하고 생성된 카드로 화면 변경
							pClient = new CatchHeroin_Client(out);
							
							if(pClient.isGaming) {
								JOptionPane.showMessageDialog(Main_Frame.this,
										"게임 진행중 입장불가!");
								return;
								
							}
							
							card2.add(pClient);
							this.getContentPane().add(card2, "card2");

							setResizable(true);
							setSize(600, 500);
							card.show(getContentPane(), "card2");// 카드 변경
							
							out.writeObject(p);
							
						}else{
							
							JOptionPane.showMessageDialog(Main_Frame.this,
									"인원이 꽉 차서 입장불가!");
							
						}

					}

					break;
				case Protocol.CLIENT_LOG_IN:
					
					pClient.setUsers(p.getUser_list(), nickName);					

					break;
				case Protocol.SEND_MSG:
					
					pClient.setMsgUser(p.getUser_list(), nickName);		
					
					break;
				case Protocol.DRAWING_CANVAS:
					
					pClient.drawCanvas(p.getX(), p.getY());
					break;
				case Protocol.CLEAR_CANVAS:
					pClient.cleanCanvas();
					break;

				case Protocol.GAME_START:
					pClient.isGaming = true; // 이번턴 게임 시작
					pClient.answer = p.getMsg();
					CatchHeroin_TurnCheck t1 = new CatchHeroin_TurnCheck(pClient);
					t1.start();
					break;
				case Protocol.EXIT_CLIENT:
					break main_thread;

				}

			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		closed();
	}

	private void closed() {
		try {
			if (in != null)
				in.close();
			if (out != null)
				out.close();
			if (s != null)
				s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		

		System.exit(0);
	}

	public static void main(String[] args) {

		new Main_Frame();
	}

}